package edu.tsinghua.oxy.engineer.service.impl;

import edu.tsinghua.oxy.common.constant.SpiderConstants;
import edu.tsinghua.oxy.common.utils.UrlUtils;
import edu.tsinghua.oxy.engineer.entity.BaseInfo;
import edu.tsinghua.oxy.engineer.entity.BookInfo;
import edu.tsinghua.oxy.engineer.entity.GovInfo;
import edu.tsinghua.oxy.engineer.repository.IBaseRepository;
import edu.tsinghua.oxy.engineer.repository.IBookRepository;
import edu.tsinghua.oxy.engineer.repository.IGovRepository;
import edu.tsinghua.oxy.engineer.service.IHtmlParse;
import edu.tsinghua.oxy.engineer.service.IJobService;
import edu.tsinghua.oxy.engineer.service.IUrlService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;

import static edu.tsinghua.oxy.common.constant.DomainConstants.*;

/**
 * 处理Job的service
 *
 * @author sean
 * @date 2021 - 07 - 29 下午1:52
 */
@Slf4j
@Service
public class JobServiceImpl implements IJobService {

    @Resource
    IUrlService urlService;

    @Resource
    IBookRepository bookRepository;

    @Resource
    IGovRepository govRepository;

    @Resource
    @Qualifier("htmlParseBook")
    IHtmlParse<BookInfo> htmlParseBook;

    @Resource
    @Qualifier("htmlParseGov")
    IHtmlParse<GovInfo> htmlParseGov;


    @Resource
    UrlUtils urlUtils;

    @Override
    public void flying() throws MalformedURLException {

        Map<String, String> poll = urlService.poll();
        // 获取高优先级URL
        String url = poll.get(SpiderConstants.SPIDER_DOMAIN_HIGHER_SUFFIX);
        boolean isHigher = true;
        if (url == null){
            // 获取低优先级URL
            url = poll.get(SpiderConstants.SPIDER_DOMAIN_LOWER_SUFFIX);
            isHigher = false;
        }
        if (url == null){
            // 没有找到要处理的URL，退出
            return;
        }

        String domain = urlUtils.getDomainName(url);
        try {
            switch (domain){
                case DOUBAN:
                    // 豆瓣
                    if (isHigher){
                        // 高优先级队列中的URL，解析列表并把详情页面写入低优先级队列
                        List<String> detailList = htmlParseBook.parseListHtml(url);
                        if (detailList.isEmpty()){
                            log.info("没有要处理的数据：{}",url);
                            break;
                        }
                        urlService.offerLower(domain,detailList);
                        String newUrl = replaceParam(url,"start",urlService.getNextPage(domain) * 20);
                        urlService.offerHigher(domain, newUrl);
                    }else {
                        // 低优先级队列中的URL，解析详情页面并持久化
                        BookInfo bookInfo = htmlParseBook.parseInfoHtml(url);
                        bookRepository.save(bookInfo);
                    }
                    break;
                case USGOV:
                    // 政府数据网
                    if (isHigher){
                        // 高优先级队列中的URL，解析列表并把详情页面写入低优先级队列
                        List<String> detailList = htmlParseGov.parseListHtml(url);
                        if (detailList.isEmpty()){
                            log.info("没有要处理的数据：{}",url);
                            break;
                        }
                        urlService.offerLower(domain,detailList);
                        String newUrl = replaceParam(url, "page", urlService.getNextPage(domain) + 1);
                        urlService.offerHigher(domain, newUrl);
                    }else {
                        // 低优先级队列中的URL，解析详情页面并持久化
                        GovInfo govInfo = htmlParseGov.parseInfoHtml(url);
                        govRepository.save(govInfo);
                    }
                    break;
                default:
                    log.error("没有找到合适的解析器");
                    return;
            }
        }catch (Exception e){
            if (isHigher) {
                urlService.offerErrorHigher(domain, url);
            }else {
                urlService.offerErrorLower(domain, url);
            }

            throw e;
        }

    }

    /**
     * 替换URL中的参数
     * @param url
     * @param param
     * @param value
     * @return
     */
    private String replaceParam(String url, String param, String value){
        String regex = "(.*)([\\?|&]"+param+"=)(\\d+)(.*)";
        String hasParam = ".*\\?.*";
        if (url.matches(regex)) {
//            return url.replaceAll(regex, "$1$2" + value + "$4");
            return url.replaceAll(regex, "$1$2" + value + "$4");
        }else if (url.matches(hasParam)){
            return url + "&" + param + "=" + value;
        }else {
            return url + "?" + param + "=" + value;
        }
    }


    /**
     * 替换URL中的参数
     * @param url
     * @param param
     * @param value
     * @return
     */
    private String replaceParam(String url, String param, Long value){
        return replaceParam(url, param, "" + value);
    }

    /**
     * 解析网页
     * @param isHigher
     * @param htmlParse
     * @param repository
     * @param domain
     * @param url
     */
    private void parseHtml(IHtmlParse htmlParse,IBaseRepository repository, boolean isHigher, String domain, String url){
        if (isHigher){
            // 高优先级队列中的URL，解析列表并把详情页面写入低优先级队列
            List<String> detailList = htmlParse.parseListHtml(url);
            urlService.offerLower(domain,detailList);
        }else {
            // 低优先级队列中的URL，解析详情页面并持久化
            BaseInfo baseInfo = htmlParse.parseInfoHtml(url);
            repository.save(baseInfo);
        }
    }

}
